package com.alipay.sofa.award.biz.service.impl;

import com.alipay.sofa.award.biz.service.facade.ActivityAwardFacade;
import com.alipay.sofa.award.common.dal.dao.AwardMapper;
import com.alipay.sofa.award.common.dal.dataobject.Award;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;

/**
 * ActivityAwardImpl
 *
 * @author yangguanchao
 * @since 2018/08/28
 */
public class ActivityAwardImpl implements ActivityAwardFacade {

    private static Logger       logger = LoggerFactory.getLogger(ActivityAwardImpl.class);

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private AwardMapper         awardMapper;

    @Override
    public int deleteByPrimaryKey(Integer id) {
        return this.transactionTemplate.execute(new TransactionCallback<Integer>() {
            @Override
            public Integer doInTransaction(TransactionStatus transactionStatus) {
                try {
                    //count
                    return awardMapper.deleteByPrimaryKey(id);
                } catch (Exception exception) {
                    transactionStatus.setRollbackOnly();
                    logger.error("deleteByPrimaryKey Error!", exception);
                    return 0;
                }
            }
        });
    }

    @Override
    public int deleteByActivityTime(String activityTime) {
        return this.transactionTemplate.execute(new TransactionCallback<Integer>() {
            @Override
            public Integer doInTransaction(TransactionStatus transactionStatus) {
                try {
                    //count
                    return awardMapper.deleteByActivityTime(activityTime);
                } catch (Exception exception) {
                    transactionStatus.setRollbackOnly();
                    logger.error("deleteByActivityTime Error!", exception);
                    return 0;
                }
            }
        });
    }

    @Override
    public int insert(Award record) {
        return this.transactionTemplate.execute(new TransactionCallback<Integer>() {
            @Override
            public Integer doInTransaction(TransactionStatus transactionStatus) {
                try {
                    //count
                    return awardMapper.insert(record);
                } catch (Exception exception) {
                    transactionStatus.setRollbackOnly();
                    logger.error("insert Error!", exception);
                    return 0;
                }
            }
        });
    }

    @Override
    public int insertWhenNoExistWithActivityTimeAndRank(Award award) {
        return this.transactionTemplate.execute(new TransactionCallback<Integer>() {
            @Override
            public Integer doInTransaction(TransactionStatus transactionStatus) {
                try {
                    Award selectedAward = awardMapper.selectByActivityTimeAndRank(
                        award.getActivityTime(), award.getRank());
                    if (selectedAward != null) {
                        //update
                        return 0;
                    } else {
                        //insert
                        return awardMapper.insert(award);
                    }
                } catch (Exception exception) {
                    transactionStatus.setRollbackOnly();
                    logger.error("insertWhenNoExistWithActivityTimeAndRank Error!", exception);
                    return 0;
                }
            }
        });
    }

    @Override
    public Award selectByPrimaryKey(Integer id) {
        return this.transactionTemplate.execute(new TransactionCallback<Award>() {
            @Override
            public Award doInTransaction(TransactionStatus transactionStatus) {
                try {
                    //count
                    return awardMapper.selectByPrimaryKey(id);
                } catch (Exception exception) {
                    transactionStatus.setRollbackOnly();
                    logger.error("selectByPrimaryKey Error!", exception);
                    return null;
                }
            }
        });
    }

    @Override
    public int updateByPrimaryKey(Award record) {
        return this.transactionTemplate.execute(new TransactionCallback<Integer>() {
            @Override
            public Integer doInTransaction(TransactionStatus transactionStatus) {
                try {
                    //count
                    return awardMapper.updateByPrimaryKey(record);
                } catch (Exception exception) {
                    transactionStatus.setRollbackOnly();
                    logger.error("updateByPrimaryKey Error!", exception);
                    return 0;
                }
            }
        });
    }

    @Override
    public int updateByActivityTimeAndRank(Award record) {
        return this.transactionTemplate.execute(new TransactionCallback<Integer>() {
            @Override
            public Integer doInTransaction(TransactionStatus transactionStatus) {
                try {
                    //count
                    return awardMapper.updateByActivityTimeAndRank(record);
                } catch (Exception exception) {
                    transactionStatus.setRollbackOnly();
                    logger.error("updateByActivityTimeAndRank Error!", exception);
                    return 0;
                }
            }
        });
    }

    @Override
    public int updateActivityTime(String oldActivityTime, String updatedActivityTime) {
        return this.transactionTemplate.execute(new TransactionCallback<Integer>() {
            @Override
            public Integer doInTransaction(TransactionStatus transactionStatus) {
                try {
                    //count
                    return awardMapper.updateActivityTime(oldActivityTime, updatedActivityTime);
                } catch (Exception exception) {
                    transactionStatus.setRollbackOnly();
                    logger.error("updateActivityTime Error by oldActivityTime=" + oldActivityTime
                                 + " and updatedActivityTime=" + updatedActivityTime, exception);
                    return 0;
                }
            }
        });
    }

    @Override
    public Award tryWinLottery(String userId, String activityTime, String rank) {
        return this.transactionTemplate.execute(new TransactionCallback<Award>() {
            @Override
            public Award doInTransaction(TransactionStatus transactionStatus) {
                try {
                    //count
                    Award expectedAward = awardMapper.selectByActivityTimeAndRank(activityTime,
                        rank);
                    if (expectedAward == null) {
                        return null;
                    }
                    int awardCount = expectedAward.getAwardCount();
                    if (awardCount <= 0) {
                        return null;
                    }
                    int updatedCount = awardMapper.minusAwardCountByActivityTimeRank(
                        expectedAward.getActivityTime(), expectedAward.getRank(), awardCount);
                    if (updatedCount > 0) {
                        //db minus one
                        expectedAward.setAwardCount(expectedAward.getAwardCount() - 1);
                        return expectedAward;
                    } else {
                        return null;
                    }
                } catch (Exception exception) {
                    transactionStatus.setRollbackOnly();
                    logger.error("tryWinLottery Error!", exception);
                    return null;
                }
            }
        });
    }

    @Override
    public int updateAwardByRankWithSameCount(Award dynamicAward) {
        if (dynamicAward == null) {
            return 0;
        }
        return this.transactionTemplate.execute(new TransactionCallback<Integer>() {
            @Override
            public Integer doInTransaction(TransactionStatus transactionStatus) {
                try {
                    //count
                    return awardMapper.updateAwardByRankWithSameCount(dynamicAward);
                } catch (Exception exception) {
                    transactionStatus.setRollbackOnly();
                    logger.error("updateAwardByRankWithSameCount Error!", exception);
                    return 0;
                }
            }
        });
    }
}
